package com.nyw.shareble;

import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import android.Manifest;
import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import java.util.List;

public class MainActivity extends AppCompatActivity  implements View.OnClickListener, BluetoothAdapter.LeScanCallback {
    //动态授权
    private static final int MY_PERMISSION_REQUEST_CODE = 10000;
    //是否打开gps
    private static final int REQUEST_CODE_OPEN_GPS = 189;
    //ble
    private BluetoothAdapter mBluetoothAdapter ;
    private int REQUEST_ENABLE=12;
    private BluetoothManager  bluetoothManager;
    private BluetoothDevice device;
    //断开连接接口
    private DisConnectBle disConnectBle;

    public void setDisConnectBle(DisConnectBle disConnectBle) {
        this.disConnectBle = disConnectBle;
    }

    //ui
    private TextView btn_startSearch,btn_stopSearch,btn_connect,btn_stopConnect,btn_sendData;
    private TextView tv_tv_msg;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        authorization();
        initView();
        initBle();
    }


    /**
     * 初始化蓝牙设备
     */
    private void initBle() {
//         mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
         bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = bluetoothManager.getAdapter();

        //检查设备是否支持蓝牙
        if (mBluetoothAdapter == null) {
            Toast.makeText(this, "不支持ble蓝牙", Toast.LENGTH_SHORT).show();
            finish();
            return;
        }


        if(!mBluetoothAdapter.isEnabled()) {
           //弹出对话框提示用户是后打开
            Intent enabler = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enabler, REQUEST_ENABLE);
            //不做提示，直接打开，不建议用下面的方法，有的手机会有问题。
            // mBluetoothAdapter.enable();

        }else {
             BluetoothManager bluetoothManager =
                    (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
            mBluetoothAdapter = bluetoothManager.getAdapter();

//            isVisibility();

        }


    }

    /**
     * 有时候扫描不到某设备，这是因为该设备对外不可见或者距离远，需要设备该蓝牙可见，这样该才能被搜索到
     * 设置蓝牙可见性，可见时间默认值为120s，最多可设置300
     */
    private void isVisibility(){
        if (mBluetoothAdapter.isEnabled()) {
            if (mBluetoothAdapter.getScanMode() !=
                    BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
                Intent discoverableIntent = new Intent(
                        BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
                discoverableIntent.putExtra(
                        BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 120);
                startActivity(discoverableIntent);
            }
        }
    }

    /**
     * view
     */
    private void initView() {
        btn_startSearch=findViewById(R.id.btn_startSearch);
        btn_startSearch.setOnClickListener(this);
        btn_stopSearch=findViewById(R.id.btn_stopSearch);
        btn_stopSearch.setOnClickListener(this);
        btn_connect=findViewById(R.id.btn_connect);
        btn_connect.setOnClickListener(this);
        btn_stopConnect=findViewById(R.id.btn_stopConnect);
        btn_stopConnect.setOnClickListener(this);
        btn_sendData=findViewById(R.id.btn_sendData);
        btn_sendData.setOnClickListener(this);
        tv_tv_msg=findViewById(R.id.tv_tv_msg);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode==REQUEST_ENABLE){
            //打开蓝牙回调结果
        }else if (requestCode == REQUEST_CODE_OPEN_GPS){
            if (checkGPSIsOpen()){
                //打开gps定位成功，执行业务处理
                mBluetoothAdapter.startLeScan(this);
            }
        }

    }

    /**
     * 6.0系统以上要动态授权
     */
    private void authorization() {
        //判断权限
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
                != PackageManager.PERMISSION_GRANTED||ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED||ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_BACKGROUND_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {
            //请求权限
            ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.ACCESS_COARSE_LOCATION,
                    Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION}, MY_PERMISSION_REQUEST_CODE);
        }else {
            //6.0系统以下业务操作
        }
    }


    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case MY_PERMISSION_REQUEST_CODE:

                boolean isAllGranted = true;


                // 判断是否所有的权限都已经授予了
                for (int grant : grantResults) {
                    if (grant != PackageManager.PERMISSION_GRANTED) {
                        isAllGranted = false;
                        break;
                    }
                }
                //做业务处理或提醒用户开启权限
                if (isAllGranted) {


                } else {
                    // 弹出对话框告诉用户需要权限的原因, 并引导用户去应用权限管理中手动打开权限按钮
                    Toast.makeText(getApplicationContext(), "获取权限失败，可能部分功能无法正常使用，请到应用权限管理中手动打开权限按钮", Toast.LENGTH_SHORT).show();
                }


        }

    }

    /**
     * 检查gps定位是否打开
     * @return
     */
    private boolean checkGPSIsOpen() {
        LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
        if (locationManager == null)
            return false;
        return locationManager.isProviderEnabled(android.location.LocationManager.GPS_PROVIDER);
    }
    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    @Override
    public void onClick(View v) {
        int id=v.getId();
        switch (id){
            case R.id.btn_startSearch:
                //搜索设备
                // 如果所有的权限都授予了, 则执行业务处理代码
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !checkGPSIsOpen()) {
                    new AlertDialog.Builder(this)
                            .setTitle(R.string.notifyTitle)
                            .setMessage(R.string.gpsNotifyMsg)
                            .setNegativeButton(R.string.cancel,
                                    new DialogInterface.OnClickListener() {
                                        @Override
                                        public void onClick(DialogInterface dialog, int which) {
                                            finish();
                                        }
                                    })
                            .setPositiveButton(R.string.setting,
                                    new DialogInterface.OnClickListener() {
                                        @Override
                                        public void onClick(DialogInterface dialog, int which) {
                                            Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                                            startActivityForResult(intent, REQUEST_CODE_OPEN_GPS);
                                        }
                                    })

                            .setCancelable(false)
                            .show();
                }else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && checkGPSIsOpen()){
                    mBluetoothAdapter.startLeScan(this);
                }else {
                    mBluetoothAdapter.startLeScan(this);
                }



                break;
            case R.id.btn_stopSearch:
                //停止搜索设备
                mBluetoothAdapter.stopLeScan(this);
                break;
            case R.id.btn_connect:
                //连接设备,为false，则直接立即连接; 为true，则等待远程设备可用时连接,并不是断开后重新连接
               device.connectGatt(this,false,mGattCallback);
                break;
            case R.id.btn_stopConnect:
                //断开连接设备
                if (disConnectBle!=null){
                    disConnectBle.disConnect();
                }
                break;
            case R.id.btn_sendData:
                //发送数据给设备

                break;

        }
    }


    @Override
    public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {

        //扫瞄搜索设备结果
        if (device.getName()!=null) {
            this.device=device;
            Log.i("dsfjslfjsifjsdf", device.getName());
        }
    }

    /**
     * 连接设备回调
     */
    private BluetoothGattCallback mGattCallback=new BluetoothGattCallback() {

        private BluetoothGatt gatt;

        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            super.onConnectionStateChange(gatt, status, newState);
            if (newState == BluetoothGatt.STATE_CONNECTED) {
                //连接状态改变回调， 发现远程设备提供的服务及其 * 特性和描述符。
                gatt.discoverServices();
                Log.i("sfljsdfisfjsd","连接成功");
            } else if (newState == BluetoothGatt.STATE_DISCONNECTED) {
                Log.i("sfljsdfisfjsd","断开连接");
            } else if (newState == BluetoothGatt.STATE_CONNECTING) {
                Log.i("sfljsdfisfjsd","正在连接中");
            } else if (newState == BluetoothGatt.STATE_DISCONNECTING) {
                Log.i("sfljsdfisfjsd","正在断开中");
            }


        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            super.onServicesDiscovered(gatt, status);
            //**发现服务回调  当远程设备的远程服务、特征和描述符 * 的列表被更新时调用回调，即发现了新的服务。**//
            //到这里才是连接成功，开始显示服务
            Log.i("sfljsdfisfjsd","连接设备成功");
            this.gatt=gatt;
            //获取service 列表
            List<BluetoothGattService>  bluetoothGattServiceList=gatt.getServices();
            //获取服务的characteristic
            List<BluetoothGattCharacteristic> bluetoothGattCharacteristicList;
            List<BluetoothGattDescriptor> bluetoothGattDescriptorList;
            for (int i=0;i<bluetoothGattServiceList.size();i++) {
                bluetoothGattCharacteristicList = bluetoothGattServiceList.get(i).getCharacteristics();
                bluetoothGattCharacteristicList.get(i).getUuid();
                //获取特征所包含的descriptor
                bluetoothGattDescriptorList= bluetoothGattCharacteristicList.get(i).getDescriptors();
                bluetoothGattDescriptorList.get(i).getUuid();
            }

//            //断开连接
//            gatt.disconnect();
//            //释放连接资源
//            gatt.close();

        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            super.onCharacteristicChanged(gatt, characteristic);
            //由于远程特征通知而触发的回调。
            /**一个ble终端可以包含多个Service，一个Service可以包含多个Characteristic，一个Characteristic包含一个value和多个Descriptor，
             * 一个Descriptor包含一个value。其中Characteristic比较重要，用的比较多。这三部分都由UUID作为唯一标示符
             * 进行接收数据的相关操作  由远程特征通知触发的回调。
            Characteristic：可以理解为一个数据类型，它包括一个value和0至多个对此characteristic的描述（Descriptor）
             Gatt：(Generic Attribute Profile)—通用属性配置文件，用于在ble链路上发送和接收被称为“属性”的数据块。
             目前所有的ble应用都是基于GATT的。一个设备可以实现多个配置文件
             Descriptor：对Characterisctic的描述，如范围、单位等
             Service：Characteristic的集合。它可以包含多个Characteristic
             BluetoothGatt：中央使用和处理数据
             BluetoothGattCallback：中央的回调
             BluetoothGattServer：周边提供数据
             BluetoothGattServerCallback：周边的回调
             BluetoothGattService：Gatt服务
             BluetoothGattCharacteristic：Gatt特性
             BluetoothGattDescriptor：Gatt描述*/
            final byte[] data = characteristic.getValue();
            if (data != null && data.length > 0) {
                Log.i("sfljsdfisfjsd",data.length+"");
            }


        }


    };

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //停止搜索
        mBluetoothAdapter.stopLeScan(this);
    }
}
